//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.Mobile.ConnectionMonitor;
using Microsoft.Practices.Mobile.ConnectionMonitor.Implementations;
using System.Collections.ObjectModel;
using Microsoft.Practices.TestUtilities;
using Microsoft.Practices.Mobile.Configuration;
using Microsoft.Practices.Mobile.ConnectionMonitor.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Practices.Mobile.ConnectionMonitor.Tests
{
	[TestClass]
	public class ConnectionMonitorFixture
	{
		[TestInitialize]
		public void InitializeConfigurationManager()
		{
			ConfigurationManager.ClearCache();
			ConfigurationManager.ConfigFileName = "App.config";
		}

		[TestMethod]
		public void FactoryCanCreateMonitorUsingConfiguration()
		{
			if (Environment.OSVersion.Platform == PlatformID.WinCE)
			{
				using (TestResourceFile res = new TestResourceFile(this, @"App.config"))
				{
					ConnectionMonitor monitor = ConnectionMonitorFactory.CreateFromConfiguration();

					Assert.IsNotNull(monitor);
					Assert.IsNotNull(monitor.Connections["CellConnection"]);
					Assert.AreEqual((uint)2, monitor.Connections["NicConnection"].Price);
				}
			}
		}

		[TestMethod]
		public void FactoryInstancePropertyReturnsAlwaysTheSameConnectionMonitorInstance()
		{
			if (Environment.OSVersion.Platform == PlatformID.WinCE)
			{
				using (TestResourceFile res = new TestResourceFile(this, @"App.config"))
				{
					ConnectionMonitor createdMonitor = ConnectionMonitorFactory.CreateFromConfiguration();
					ConnectionMonitor monitorInstance = ConnectionMonitorFactory.Instance;
					ConnectionMonitor monitorInstance2 = ConnectionMonitorFactory.Instance;

					Assert.AreSame(createdMonitor, monitorInstance);
					Assert.AreSame(createdMonitor, monitorInstance2);
				}
			}
		}

		[TestMethod]
		public void CanCreateConnectionMonitor()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();
			Assert.IsNotNull(monitor);
		}

		[TestMethod]
		public void CanEnumerateConnections()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();
			foreach (Connection connection in monitor.Connections)
			{
			}
		}

		[TestMethod]
		public void CanAddConnection()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();

			NetworkConnection expected = new NetworkConnection("Ethernet", 5);

			monitor.Connections.Add(expected);

			Connection actual = monitor.Connections["Ethernet"];

			Assert.AreSame(expected, actual);
		}

		[TestMethod]
		public void SpecificConnectionExposesStateChanges()
		{
			bool firedEvent = false;
			MockConnection connection = new MockConnection("Mock", 5);

			connection.StateChanged += delegate(object sender, StateChangedEventArgs args)
			{
				Assert.AreSame(connection, sender);
				bool connected = args.IsConnected;
				firedEvent = true;
			};

			connection.MockConnect();

			Assert.IsTrue(firedEvent);
		}

		[TestMethod]
		public void CanDetermineIfConnectionIsConnected()
		{
			MockConnection connection = new MockConnection("Mock", 8);
			bool isConnected = connection.IsConnected;
			Assert.IsFalse(isConnected);
		}

		[TestMethod]
		public void ConnectionHasType()
		{
			string expected = "Foo";
			MockConnection connection = new MockConnection(expected, 5);
			string actual = connection.ConnectionTypeName;

			Assert.AreEqual(expected, actual);
		}

		[TestMethod]
		public void CanGetActiveConnections()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();
			MockConnection expected = new MockConnection("Mock", 8);

			monitor.Connections.Add(expected);
			expected.MockConnect();

			Assert.AreEqual(1, monitor.ActiveConnections.Count());
			Assert.AreSame(expected, monitor.ActiveConnections.First());
		}

		[TestMethod]
		public void CanGetActiveNetworkName()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();
			MockConnection connection = new MockConnection("Mock", 8);
			string expected = "Internet";

			monitor.Connections.Add(connection);

			connection.MockConnect();
			string actual = monitor.ActiveConnections.First().GetNetworkName();

			Assert.AreSame(expected, actual);
		}

		[TestMethod]
		public void CanGetActiveConnectionPrice()
		{
			uint expected = 8;
			ConnectionMonitor monitor = new ConnectionMonitor();
			MockConnection connection = new MockConnection("Mock", expected);

			monitor.Connections.Add(connection);
			connection.MockConnect();
			uint actual = monitor.ActiveConnections.First().Price;

			Assert.AreEqual(expected, actual);
		}

		[TestMethod]
		public void AddingNullToConnectionsThrowsArgumentNullException()
		{
			ConnectionMonitor monitor = new ConnectionMonitor();
			MockConnection expected = new MockConnection("Mock", 8);

			ExtendedAssert.Throws<ArgumentNullException>(
						delegate { monitor.Connections.Add(null); });
		}

		#region Mocks


		class NetworkConnection : Connection
		{
			public NetworkConnection(string name, uint price)
				: base(name, price)
			{
			}

			public override bool IsConnected
			{
				get { return false; }
			}

			public override string GetNetworkName()
			{
				return string.Empty;
			}

			public override string GetDetailedInfoString()
			{
				return "Mock Network Connection";
			}
		}

		class MockConnection : Connection
		{
			public MockConnection(string name, uint price)
				: base(name, price)
			{
			}

			private bool isConnected = false;

			public override bool IsConnected
			{
				get { return isConnected; }
			}

			public void MockConnect()
			{
				bool previousState = isConnected;
				isConnected = true;
				if (previousState == false)
				{
					StateChangedEventArgs arg = new StateChangedEventArgs(isConnected, "Internet");
					RaiseStateChanged(arg);
				}
			}

			public void MockDisconnect()
			{
				bool previousState = isConnected;
				isConnected = false;
				if (previousState == true)
				{
					StateChangedEventArgs arg = new StateChangedEventArgs(isConnected, "Internet");
					RaiseStateChanged(arg);
				}
			}

			public override string GetNetworkName()
			{
				return "Internet";
			}

			public override string GetDetailedInfoString()
			{
				return "MockConnection";
			}
		}


		#endregion

		#region ConfigurationFixture

		//<Connections>
		//	<ConnectionItems>
		//		<add  Type="CellConnection" Price="8"/>
		//		<add  Type="NicConnection" Price="2"/>
		//		<add  Type="DesktopConnection" Price="1"/>
		//	</ConnectionItems>
		//</Connections>

		[TestMethod]
		public void GetConnectionsSectionDoesntGetNull()
		{
			using (TestResourceFile resFile = new TestResourceFile(this, @"App.config"))
			{
				ConnectionSettingsSection section = (ConnectionSettingsSection)ConfigurationManager.GetSection("Connections");
				Assert.IsNotNull(section);
			}
		}

		[TestMethod]
		public void SectionGetConnectionItemsCollectionDoesntGetNull()
		{
			using (TestResourceFile resFile = new TestResourceFile(this, @"App.config"))
			{
				ConnectionSettingsSection section = (ConnectionSettingsSection)ConfigurationManager.GetSection("Connections");

				Assert.IsNotNull(section.ConnectionItems);
			}
		}

		[TestMethod]
		public void SectionGetEndpointItemsCollectionContainsSameQuantityThanAppConfig()
		{
			using (TestResourceFile resFile = new TestResourceFile(this, @"App.config"))
			{
				ConnectionSettingsSection section = (ConnectionSettingsSection)ConfigurationManager.GetSection("Connections");

				Assert.AreEqual(3, section.ConnectionItems.Count);
			}
		}

		[TestMethod]
		public void ConnectionItemsInConnectionCollectionAreTheSameThanAppConfig()
		{
			using (TestResourceFile resFile = new TestResourceFile(this, @"App.config"))
			{
				ConnectionSettingsSection section = (ConnectionSettingsSection)ConfigurationManager.GetSection("Connections");

				foreach (ConnectionItemElement itemConnection in section.ConnectionItems)
				{
					switch (itemConnection.Type)
					{
						case "NicConnection":
							Assert.AreEqual((uint)2, itemConnection.Price);
							break;
						case "DesktopConnection":
							Assert.AreEqual((uint)1, itemConnection.Price);
							break;
						case "CellConnection":
							Assert.AreEqual((uint)8, itemConnection.Price);
							break;
						default:
							Assert.Fail();
							break;
					}
				}

				Assert.AreEqual(3, section.ConnectionItems.Count);
			}
		}

		#endregion
	}
}
